﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using CLUBsInterpreter.AST;
using CLUBsInterpreter.ObjectTypes;

namespace CLUBsInterpreter
{
	/**
	 * <summary>
	 * Main class for the CLUBs interpreter command-line program.
	 * </summary>
	 **/
    class Program
	{
		/**
		 * <summary>
		 * Entry-point for the CLUBs interpreter command-line program.
		 * </summary>
		 **/
        static void Main(string[] args)
        {
			// Check if we have enough arguments
			if (args.Length < 1)
			{
				// If not, print usage information
				Console.WriteLine("usage: " + System.AppDomain.CurrentDomain.FriendlyName + " source [-tc] [-tf file]");
				Console.ReadKey();
				return;
			}

			// Print information
            Console.WriteLine("Scanning " + args[0]);
			// Initiate the scanner
            Scanner scan = new Scanner(args[0]);
			// Initiate the parser
			Parser pars = new Parser(scan);
			// Initiate the AST
			pars.ast = new CLUBsNode();
			// Initiate the identification table
			pars.idt = new IdentificationTable("__root__");
			// Print information
			Console.WriteLine("Parsing input file");
			// Parse the source file
			pars.Parse();

			// Check for parsing errors
			if (pars.errors.count > 0)
			{
				Console.WriteLine("FATAL ERROR: Parsing failed.");
				Console.ReadKey();
				return;
			}

			// Print information
			Console.WriteLine("Performing contextual analysis");
			// Initiate contextual analyzer
			Visitor ca = new Visitor(Console.Error, pars.idt, new StandardEnvironment());
			// Perform contextual analysis
			pars.ast.Visit(ca);

			// Print identification tree for debugging
			//pars.idt.PrintTree(Console.Out);

			ca.PopulateGlobalVars();

			pars.idt.SetObjectParents();

			// Clear the identification tree used by the contextual analyzer
			pars.idt.ClearTree();

			// Check for contextual errors
			if (ca.Errors > 0)
			{
				Console.WriteLine("FATAL ERROR: Contextual analysis failed.");
				Console.ReadKey();
				return;
			}


			// Print AST to console
			if (args.Contains("-tc"))
			{
				Console.WriteLine("Printing abstract syntax tree\n----------------------------------");

				pars.ast.PrintTree(Console.Out, 0);

				Console.WriteLine("----------------------------------");
			}
			
			// Print AST to file
			if (args.Contains("-tf"))
			{

				string fname = args[Array.IndexOf(args, "-tf") + 1];

				Console.WriteLine("Printing abstract syntax tree to file '"+fname+"'");

				FileStream file = new FileStream(fname, FileMode.Append, FileAccess.Write);
				StreamWriter writer = new StreamWriter(file);

				writer.WriteLine("\r\n##########################################################\r\n   Abstract syntax tree of "+args[0]+" \r\n##########################################################");

				pars.ast.PrintTree(writer, 0);

				writer.Flush();
				writer.Close();
			}

			Console.WriteLine("Starting execution");

			// TODO: Instantiate Interpreter object and interpret the decorated AST.
            Interpreter interpreterObject = new Interpreter(Console.Out, pars.ast);

			interpreterObject.StartGame();

			// Check for execution errors
			if (interpreterObject.Errors > 0)
			{
				Console.WriteLine("FATAL ERROR: Execution failed.");
				Console.ReadKey();
				return;
			}

			// Print information
			Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}
